/**
* @file         
* @brief		循环队列，数组方式.
* @details	    基本功能演示.
* @author		conkty@126.com
* @date		    2023
* @version	    v0.1
* @par 更新记录:         
*	v0.1: 初建\n
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>

const unsigned int MAX_SIZE = 5;

typedef struct ElemType {
    int id;
    float value;
} Node;

typedef struct queue_array {
    Node* data;
    int front;
    int rear;
} Queue;

int length(Queue *Q);

void initial(Queue* Q) {
    Q->data = NULL; // 预先置0便于后续判断
    Q->data = malloc(MAX_SIZE * sizeof(Node));
    if(NULL == Q->data) {
        printf("malloc failed! exit!\n");
        exit(-1);
    }

    // 全部内容初始化为空(0)
    memset(Q->data, 0, MAX_SIZE * sizeof(Node));
    Q->front = 0;
    Q->rear = 0;
}

void traverse(Queue* Q) {
    printf("front %d rear %d\n", Q->front, Q->rear);
    printf("size %d\n", length(Q));

    for (int i = Q->front; i < Q->rear; ++i) {
        printf("%d ", Q->data[i].id);
    }
    printf("\n");
}

int length(Queue* Q) {
    return (Q->rear - Q->front + MAX_SIZE) % MAX_SIZE;
}

int push(Queue* Q, Node* e) {
    if ((Q->rear + 1)%MAX_SIZE == Q->front) {
        printf("que is full %d~%d, push failed, id is %d .\n",Q->front, Q->rear, e->id);
        return -1;
    }

    printf("pushing node with id %d ...\n", e->id);

    // 循环起来
    Q->data[Q->rear] = *e;
    Q->rear = (Q->rear + 1)%MAX_SIZE;

    return 0;
}

Node* pop(Queue* Q) {
    if(0 == (Q->rear - Q->front)) {
        printf("que is empty, pop faild.\n");
        return NULL;
    }

    //循环起来
    Node *e = &Q->data[Q->front];
    Q->front = (Q->front + 1)%MAX_SIZE;

    printf("node %d is poped.\n", e->id);

    return e;
}

Node* top(Queue* Q) {
    if(0 == (Q->rear - Q->front)) {
        printf("queue is empty, pop faild.\n");
        return NULL;
    }

    return &Q->data[Q->front];
}

void pop_test(Queue* Q) {
    Node *e = pop(Q);
    if(NULL != e) {
        printf("succeed to pop %d\n", e->id);
    } else {
        printf("faild to pop.\n");
    }
}

void top_test(Queue* Q) {
    Node *e = top(Q);
    if(NULL != e) {
        printf("succeed to get top %d\n", e->id);
    } else {
        printf("faild to get top.\n");
    }
}


int main()
{
    Queue Q;
    initial(&Q);
    traverse(&Q);

    for (int i = 10; i < 23; ++i)
    {
        Node a = {i, 0.0};
        push(&Q, &a);

        if(i%3 == 0)
            pop(&Q);
    }

    traverse(&Q);

    pop_test(&Q);
    traverse(&Q);

    top_test(&Q);

    return 0;
}